#!/bin/env python

import random

class Fuzz:
    def fuzz(self): pass
    def __str__(self): return "I:" + str(self.value())
    def __int__(self): return int(str(self.value()))
    def value(self): return repr(self)
    def write(self, out, string): out.write(str(string))
    def fuzz(self, out): self.write(out, "unimplemented")

class Seq(Fuzz):
    def __init__(self, *rules): self.seq = list(rules)
    def append(self, rule):
        self.seq.insert(0, rule)
        return self

    def fuzz(self, out):
        for r in self.seq: r.fuzz(out)

class Empty(Fuzz):
    def append(self, rule): return rule
    def fuzz(self, out): pass

class Atom(Fuzz):
    def append(self, rule): return Seq(rule, self)
    def fuzz(self, out): self.write(out, self.value())

class Set(Atom):
    def __init__(self, *items): self.items = list(items)
    def doinsert(self, item):
        self.items.insert(0, item)
        return self

    def insert(self, item): return self.doinsert(item)
    def fuzz(self, out): return random.choice(self.items).fuzz(out)

class Range(Fuzz):
    def __init__(self): pass

class Cont(Atom):
    def __init__(self, value): self._value = value
    def value(self): return self._value

class Var(Fuzz):
    def __init__(self, name, content): pass

class Id(Cont): pass

class Args(Fuzz): pass

class Function(Fuzz):
    def __init__(self, name, args = Args()):
        self.name = name
        self.args = args

class Space(Cont): pass

class Number(Cont):
    def __init__(self, value): self._value = int(value)

class Item(Fuzz):
    def __init__(self, rules, rate = Number("1")):
        self.rules = rules
        self.rate  = int(rate)
    def value(self): return self.rules.value()
    def fuzz(self, out): self.rules.fuzz(out)

class Chars(Set):
    def insert(self, item):
        v = item.value()
        for ch in v[:-1]: self.doinsert(Item(Id(ch)))
        return self.doinsert(Item(Id(v[-1]), item.rate))
